<!DOCTYPE html>
<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
	layout:decorate="~{common/layout}">

<head>
	<meta charset="UTF-8">
	<title>项目详情</title>
	<script th:src="@{/base/js/x6node.js}"></script>
	<link rel="stylesheet" th:href="@{/base/css/node.css}" />
	<style>
		#containerTool {
			width: 100px;
			height: 100%;
			/**position: relative;**/
			display: flex;
			flex-direction: column;
			align-items: center;
			border-right: 1px solid #dfe3e8;
			text-align: center;
			font-size: 12px;

			.x6-widget-stencil {
				background-color: rgb(255, 255, 255);
			}

			.x6-widget-stencil-title {
				background: #eee;
				font-size: 1rem;
			}

			.x6-widget-stencil-group-title {
				/**font-size: 1rem !important;**/
				height: 30px !important;
				background-color: #ffffff !important;
				text-align: left !important;
			}
		}

		g[data-shape="dag-node"] {
			color: #eee
		}

		.x6-widget-stencil-search-text {
			border-radius: 1px !important;
		}

		.el-table__row {
			cursor: pointer;
		}
		.el-collapse-item__content {
			padding-bottom: 0px!important;
		}
		.customer-node-box {
			cursor: move;
		}
		.customer-node-box-not {
			cursor: no-drop;
		}
		.customer-node-box-not span {
			color: #d3d3d3!important;
		}
		.el-timeline-item {
		    margin-left: -30px!important;
		    width: 200px!important;
		}
		.el-collapse-item__header {
			font-weight: 800;
		}
		.el-button-group>.el-button:not(:last-child) {
		    margin-right: 1px!important;
		}
	</style>
</head>

<body>
	<div layout:fragment="fragment_body">
		<div class="toolbar">
			<div style="margin-right: 12px; width: 40%;">
				<el-button type="text" icon="Back" @click="backList"></el-button> &nbsp; &nbsp;{{project?.projectName}}
				<!--<my-component :obj="graphSelectNode" ></my-component>-->
				<!--<my-money v-model="testTxt1" :decimal_point="testTxt"></my-money>-->
			</div>
			<div style="flex: 1 1 0%;">
				<!--<el-button-group>
					<el-button @click="changeStatus(null)" :type="''" icon="Document">项目数据</el-button>
					<el-button @click="changeStatus(1)" :type="''" icon="CircleCheck">模型训练</el-button>
					<el-button @click="changeStatus(0)" :type="''" icon="CircleClose">模型管理</el-button>
				</el-button-group>-->
				<el-text>运算状态：{{jobState}}</el-text>
			</div>
			<!--<el-button type="primary" @click="openForm" icon="DocumentAdd">提交模型</el-button>-->
		</div>
		<!-- buju  -->
		<el-row :gutter="10" style="margin-top:20px;">
			<el-col :span="4">
				<el-tabs v-model="leftToolVal" stretch="true" type="border-card" @tab-click="handleLeftToolClick">
					<el-tab-pane label="训练流" name="trainFlow">
						<el-table ref="flowTableRef" :data="flowData" show-header="false" highlight-current-row
							style="width: 100%" empty-text="请创建训练流" @current-change="handleFlowChange">
							<el-table-column property="flowTitle"></el-table-column>
							<el-table-column property="flowId" width="60">
								<template #default="scope">
									<el-button type="danger" size="small" icon="Delete" plain
										@click="delFlow(scope.row.flowId)"></el-button>
								</template>
							</el-table-column>
						</el-table>
						<div style="margin: 0 auto;width:50%" v-show="project?.projectFinish != 1">
							<el-popover :visible="flowFormVisible" placement="top" :width="200">
								<span>训练流名称</span>
								<el-input v-model="flowTitle" style="width: 100%" placeholder="..."
									prefix-icon="ScaleToOriginal"></el-input></br>
								<div style="text-align: right; margin: 0; margin-top: 5px">
									<el-button size="small" text
										@click="flowFormVisible = false;flowTitle = ''">关闭</el-button>
									<el-button size="small" type="primary" @click="saveFlow">
										保存
									</el-button>
								</div>
								<template #reference>
									<el-button type="text" @click="flowFormVisible = true"
										icon="ScaleToOriginal">创建训练流</el-button>
								</template>
							</el-popover>
						</div>
					</el-tab-pane>
					<el-tab-pane label="组件库" name="component">
						<div id="containerTool" :style="'width: 100%;height: '+(elelMianHeight * 1 - 160)+'px;'"></div>
					</el-tab-pane>
					<el-tab-pane label="数据集" name="dataMap">
						<el-alert title="仅展示已授权数据" type="info"></el-alert>
						<el-collapse v-model="activeNames" @change="handleChange">
							<el-collapse-item :name="invite.inviteId"
								v-for="(invite, index) in inviteData">
								<template #title>
									<el-icon color="green" style="margin-right: 5px">
										<Connection></Connection>
									</el-icon>
									{{invite.nodeCode}}
								</template>
								<el-popover trigger="click" :visible="selectInviteId == invite.inviteId" 
									placement="top" :width="250"  v-if="invite.data == null">
								    <template #default>
										<el-select
									      v-model="selectDataId"
									      placeholder="请选择授权数据"
									      style="width: 100%"
									    >
									      <el-option
									        v-for="item in notAuthDatas"
									        :key="item.dataId"
									        :label="item.dataTitle"
									        :value="item.dataId"
									      ></el-option>
									    </el-select>
									    <div style="text-align: right; margin-top: 5px">
									      <el-button size="small" text @click="closeInvite()">返回</el-button>
									      <el-button size="small" type="primary" @click="saveInvite()">
									        确认授权
									      </el-button>
									    </div>
									</template>
								    <template #reference>
								      <el-button type="text" icon="Pointer" @click="openInvite(invite.inviteId, invite.nodeId)">授权数据</el-button>
								    </template>
							  </el-popover>
							   {{invite.data?'表名：'+invite.data.dataTitle:''}}
								<el-table :ref="'dataTableRef' + invite.inviteId" :data="invite.data.columns"
									style="width: 100%" v-if="invite.data != null" size="small">
									<el-table-column property="name" label="字段名"></el-table-column>
									<el-table-column property="type" label="类型"></el-table-column>
									<el-table-column property="remark" label="备注"></el-table-column>
								</el-table>
							</el-collapse-item>
						</el-collapse>
					</el-tab-pane>
				</el-tabs>
			</el-col>
			<el-col :span="16">
				<div style="display: flex; justify-content: space-between;width: 100%;">
					<div>
						<el-button-group>
							<el-button color="#626aef" icon="VideoPlay" plain @click="startJob(0)" :disabled="jobState != 'READY'" >全部执行</el-button>
							<el-button type="info" icon="CaretRight" plain @click="startJob(1)" :disabled="flowId == null || graphSelectNode == null" >执行单节点</el-button>
							<el-button type="danger" icon="VideoPause" plain @click="stopJob" :disabled="jobState == 'RUNNING'?false:true">停止</el-button>
							<el-button type="success" icon="Refresh" plain @click="startJob(2)" v-show="jobState == 'FAILED' || jobState == 'STOPED'">恢复</el-button>
							<!--<el-button type="" icon="ArrowLeftBold" plain :disabled="!canUndo"
								@click="graph.undo()">撤销</el-button>
							<el-button type="" icon="ArrowRightBold" plain :disabled="!canRedo"
								@click="graph.redo()">重做</el-button>-->
						</el-button-group>
					</div>
					<div>
						<el-button type="success" @click="saveGraph" icon="DocumentAdd"
							:disabled="jobState != 'READY'">保存流程</el-button>
					</div>
				</div>
				<div id="container"
					style="margin-top:5px;min-height:500px;border: 1px solid #dcdfe6;" v-show="flowData != null && flowData.length > 0">
				</div>
				<div v-show="flowData == null || flowData.length == 0" :style="'margin-top:5px;background-image: url(/base/img/guide.svg);background-repeat: no-repeat;background-position: 50% 30%;background-size: 512px 275px;border: 1px solid #dcdfe6;min-height:' + (elelMianHeight * 1 - 130) + 'px;'">
				</div>
				<el-drawer
			        v-model="jobLogDrawer"
			        title="执行日志"
			        append-to-body="true"
			        :before-close="handleClose"
					direction="rtl"
					style="width: 500px"
					v-drawerDrag
			      >
			        <div>
					<el-text tag="p" v-for="(err, eindex) in jobLogDrawerText" >
						<b style="color:red">{{eindex + 1}}</b>
						：{{err}}
					</el-text>
					</div>
			      </el-drawer>
			</el-col>
			<el-col :span="4">
				<el-tabs v-model="rightToolVal" stretch="true" type="border-card" @tab-click="handleRightToolClick">
					<el-tab-pane label="属性" name="nodeProp" :style="'width: 100%;min-height:300px;max-height: '+(elelMianHeight * 1 - 160)+'px;overflow: hidden;overflow-y: auto;'">
						<el-empty description="点击节点后配置" v-if="graphSelectNode == null"></el-empty>
						<el-form ref="nodeAttrForm" :model="nodeAttrForm" v-if="graphSelectNode != null"  class="form-itemsmall"
							size="small" label-position="top" label-width="auto" style="width: 100%">
							<el-collapse v-model="activeCollapse" accordion="true">
								<el-collapse-item title="组件描述" name="desc" v-if="nodeAttrForm && nodeAttrForm.desc != null">
									<div class="el-form-item__label" style="height: unset;">{{nodeAttrForm.desc}}</div>
								</el-collapse-item>
								<el-collapse-item v-if="nodeAttrForm.attrs && nodeAttrForm.attrs.length > 0" title="节点配置" name="needAttr">
									<e-col v-for="(nodeAttr, nIndex) in nodeAttrForm.attrs" >
										<e-col v-if="nodeAttr.required == true">
											<node-attr @attrconfig="noedAttrHandle" :nodeid="nodeAttrForm.graphId" :nodecode="nodeAttrForm.code" 
											:nodeindex="nIndex" :nodeattr="nodeAttr" :nodeattrs="nodeAttrForm.attrs" :nodesave="jobState == 'READY'"></node-attr>
										</e-col>
									</e-col>
									<el-switch
									    v-if="nodeAttrForm.showSwitch"
										v-model="nodeAttrForm.showDef"
									    inline-prompt
									    active-text="高级配置"
									    inactive-text="关闭高级"
									 ></el-switch>
									<e-col v-show="nodeAttrForm.showDef" v-for="(nodeAttr, nIndex) in nodeAttrForm.attrs"  >
										<e-col v-if="nodeAttr.required == false">
											<node-attr @attrconfig="noedAttrHandle" :nodeid="nodeAttrForm.graphId" :nodecode="nodeAttrForm.code" 
											:nodeindex="nIndex" :nodeattr="nodeAttr" :nodeattrs="nodeAttrForm.attrs" :nodesave="jobState == 'READY'"></node-attr>
										</e-col>
									</e-col>
								</el-collapse-item>
								<el-collapse-item v-if="nodeAttrForm.inds && nodeAttrForm.inds.length > 0" title="输入" name="toIn">
									<e-col v-for="(nodeIn, iIndex) in nodeAttrForm.inds" >
										<el-tag type="info">{{nodeIn.code}}:{{nodeIn.desc}}</el-tag>
									</e-col>
									<!--<e-col v-for="(nodeIn, iIndex) in nodeAttrForm.inds" >
										<node-ind :indata="nodeIn" :inindex="iIndex"></node-ind>
										<el-form-item 
											v-if="nodeIn != null && nodeAttrForm.code == 'read_data'"
											:prop="`nodeAttrForm.inds[${iIndex}].prop`"
											:required="nodeIn.required"
											:rules='[{trigger: "change", message: "不能为空", required: true}]'
											>
											<el-button 
											:type="nodeIn.prop?'success':'info'" plain
											@click="noedAttrHandle(nodeAttrForm.graphId,nodeAttrForm.code, 'prop', iIndex)">{{nodeIn.prop?'已配置':'配置数据'}}
											</el-button>
										</el-form-item>
									</e-col>-->
								</el-collapse-item>
								<el-collapse-item v-if="nodeAttrForm.outds && nodeAttrForm.outds.length > 0" title="输出" name="toOut">
									<e-col v-for="(nodeOut, oIndex) in nodeAttrForm.outds" >
										<el-tag type="info">{{nodeOut.code}}:{{nodeOut.desc}}</el-tag>
									</e-col>
								</el-collapse-item>
							</el-collapse>
						    <el-form-item class="mt-5" v-show="nodeAttrForm.code != null">
						      <el-button :type="(nodeAttrForm.paramId != null)?'success':'primary'" :disabled="jobState != 'READY'" @click="saveNodeAttr">{{(nodeAttrForm.paramId != null)?'修改':'保存'}}配置</el-button>
						      <el-button>重置</el-button>
						    </el-form-item>
						</el-form>
					</el-tab-pane>
					<el-tab-pane label="日志" name="log" :style="'width: 100%;min-height:300px;max-height: '+(elelMianHeight * 1 - 160)+'px;overflow: hidden;overflow-y: auto;'">
						<el-empty description="执行任务后产生日志与结果" v-if="taskLogs == null || taskLogs.length == 0"></el-empty>
						<!--<node-log :logs="taskLogs" @=""></node-log>-->
						<el-timeline >
						    <el-timeline-item
						      v-for="(timeline, index) in taskLogs"
						      :key="index"
						      hollow="true"
						      size="large"
						      :icon="timeline.icon"
						      :color="timeline.color"
						      :timestamp="timeline.dataTime"
						      placement="top"
						    >
						      {{ timeline.status }}
							  <el-button v-if="timeline.status == 'FAILED'" type="danger" size="small" plain @click="loadTaskLog(timeline.content)" >查看日志</el-button>
						    </el-timeline-item>
						  </el-timeline>
					</el-tab-pane>
				  <el-tab-pane label="结果" name="result" :style="'width: 100%;min-height:300px;max-height: '+(elelMianHeight * 1 - 160)+'px;overflow: hidden;overflow-y: auto;'">
				  	<el-empty description="执行任务后产生结果" v-if="resultDatas == null || resultDatas.length == 0"></el-empty>
					<el-table ref="resultDataRef" v-if="resultDatas != null && resultDatas.length > 0" 
						:data="resultDatas" highlight-current-row style="width: 100%">
						<el-table-column property="graphCode" ></el-table-column>
						<el-table-column property="name" >
							<template #default="scope">
								<el-button type="primary" size="small" link
								@click="showResultData(scope.row.domainDataId)">{{scope.row.name}}</el-button>
							</template>
						</el-table-column>
						<!--<el-table-column property="domainDataId" width="60">
							<template #default="scope">
								<el-button type="danger" size="small" icon="View" plain
									@click="showResultData(scope.row.domainDataId)">查看</el-button>
							</template>
						</el-table-column>-->
					</el-table>
				  </el-tab-pane>
				</el-tabs>
			</el-col>
		</el-row>
		<!--节点详情-->
		<el-drawer v-model="attrConfigDrawer" :with-header="false" direction="ltr" :show-close="false"
			:close-on-click-modal="false" :close-on-press-escape="false">
		    <template #footer>
		      <div style="flex: auto">
		        <el-button @click="cancelAttrConfigClick">返回</el-button>
		        <el-button type="primary" @click="confirmAttrConfigClick">保存</el-button>
		      </div>
		    </template>
			<h5>您可以在此界面配置属性值</h5>
			<el-text>
				<el-icon><ElementPlus /></el-icon>
			    请从一下字段中选中
			</el-text>
			<el-form :model="attrForm" label-width="auto" style="margin-top: 10px;max-width: 600px">
				<el-form-item label="可选项" v-if="attrForm.type == 'SELECT' || attrForm.type == 'GROUP'">
			      <el-select v-model="attrForm.value" multiple :multiple-limit="attrForm.limit" placeholder="请选择">
					<el-option
						v-if="attrForm.type == 'SELECT'"
						v-for="item in attrForm.items"
				        :key="item.value"
				        :label="item.label"
				        :value="item.value"
				     ></el-option>
					 <el-option-group
						 v-if="attrForm.type == 'GROUP'"
						 v-for="group in attrForm.items"
				        :key="group.value"
				        :label="group.label"
					     >
					       <el-option
					         v-for="option in group.options"
					         :key="option.value"
					         :label="option.label"
					         :value="option.value"
							 ></el-option>
				     </el-option-group>
			      </el-select>
			    </el-form-item>
				<el-form-item label="填写内容" v-if="attrForm.type == 'INPUT'">
					<el-input v-model="attrForm.value" ></el-input>
				</el-form-item>
			</el-form>
		  </el-drawer>
	</div>
</body>
<script type="text/javascript" layout:fragment="fragment_script">
	const _data = {
		leftToolVal: 'component',
		rightToolVal: 'nodeProp',
		attrConfigDrawer: false,
		graph: null,
		graphSelectNode: null,
		stencil: null,
		canRedo: false,
		canUndo: false,

		projectId: null,
		project: null,
		jobState: 'READY',
		taskStatueInterval: null,
		flowId: null,
		flowTitle: '',
		flowFormVisible: false,
		flowData: [],

		inviteData: [],
		selectInviteId: null,
		selectNodeId: null,
		selectDataId: null,
		
		activeCollapse: 'needAttr',
		nodeAttrForm: {},
		taskLogs: [],
		resultDatas: [],
		
		jobLogDrawer: false,
		jobLogDrawerText: [],
		
		attrForm: {
			type: null,
			limit: 1,
			items: [],
			value: null
		}
	}
	const _method = {
		backList() {
			window.location.href = '/project'
		},
		handleLeftToolClick() {

		},
		handleRightToolClick() {

		},
		initGraph() {
			this.$nextTick(() => {
				let graph = new X6.Graph({
					container: document.getElementById('container'),
					width: '100%',
					height: that.elelMianHeight * 1 - 130,
					history: true,
					background: {
						color: '#ffffff',//#F2F7FA
					},
					panning: {
						enabled: true,
						eventTypes: ['leftMouseDown', 'mouseWheel'],
					},
					mousewheel: {
						enabled: true,
						modifiers: 'ctrl',
						factor: 1.1,
						maxScale: 1.5,
						minScale: 0.5,
					},
					highlighting: {
						magnetAdsorbed: {
							name: 'stroke',
							args: {
								attrs: {
									fill: '#fff',
									stroke: '#31d0c6',
									strokeWidth: 4,
								},
							},
						},
					},
					connecting: {
						snap: true,
						allowBlank: false,
						allowLoop: false,
						highlight: true,
						allowNode: false,
						connector: 'algo-connector',
						connectionPoint: 'anchor',
						anchor: 'center',
						validateMagnet({magnet}) {
							return magnet.getAttribute('port-group') !== 'top'
						},
						createEdge() {
							return graph.createEdge({
								shape: 'dag-edge',
								attrs: {
									line: {
										stroke: '#C2C8D5',
										strokeWidth: 1,
										strokeDasharray: '5 5',
									},
									targetMarker: {
										name: 'block',
										width: 12,
										height: 8,
									},
								},
								zIndex: 0,
							})
						},
					}
				})
				graph.use(
					new X6PluginSnapline.Snapline({
						enabled: true,
					})
				)
				graph.use(
					new X6PluginHistory.History({
						enabled: true,
					})
				)
				graph.use(
				  new X6PluginSelection.Selection({
				    	enabled: true, 
			        	showNodeSelectionBox: true,
				  }),
				)
				graph.use(
				  new X6PluginDnd.Dnd({
				    	enabled: true,
				    	target: that.graph,
						getDragNode: (node) => node.clone({keepId: true}),
						getDropNode: (node) => node.clone({keepId: true}),
				  }),
				)
				graph.use(
				  new X6PluginKeyboard.Keyboard({
			        enabled: true,
			        global: true,
			      })
				)
				graph.on('node:selected', (e) => {
					that.graphSelectNode = e.node
					if(e.cell.data.status == 'FAILED'){
						that.loadTaskLog(e.node.id)
					}
				})
				graph.on('node:added', (e) => {
					//debugger
					if(e.node.id.length > 13){
						/**const ports = e.node.port.ports.map((port, i) => ({
							group: port.group,
							id: "port-" + new Date().getTime() + "-" + ( Math.floor(Math.random() * 10000) + 1)
						}));
						e.node.removePorts();
						e.node.addPorts(ports);**/
						
						//getRequst('/graph/createId').then(function (resp) {
							//graph.updateCellId(e.node, resp.data)
						//})
					}
				})
				graph.on('node:unselected', (e) => {
					that.graphSelectNode = null
					that.nodeAttrForm = {}
					e.cell.removeTools()
				})
				/**graph.on('edge:selected', (edge) => {
					console.log(`edge selected: ${edge}`)
					console.log(edge)
				})**/
				graph.on('history:change', (e) => {
					that.canRedo = that.graph.canRedo()
					that.canUndo = that.graph.canUndo()
				})
				// undo redo
				graph.bindKey(['meta+z', 'ctrl+z'], () => {
				  if (graph.canUndo()) {
				    	graph.undo()
				  }
				  return false
				})
				graph.bindKey(['meta+y', 'ctrl+y'], () => {
				  if (graph.canRedo()) {
				    	graph.redo()
				  }
				  return false
				})
				that.graph = graph

				that.initTool();
				// 配置侧边菜单
				that.initStencil()
				// 配置事件
				that.initEvent()
			})
		},
		initStencil() {
			let that = this
			getRequst('/graph/graphGroup').then(function (resp) {
				stencil = new X6PluginStencil.Stencil({
					title: '流程图组件',
					target: that.graph,
					stencilGraphWidth: 260,
					stencilGraphHeight: 0,
					collapsable: true,
					search(cell, keyword) {
						return cell.getData().label.indexOf(keyword) !== -1
					},
					placeholder: '请输入组件名',
					notFoundText: '找不到该组件',
					groups: resp.data,
					layoutOptions: {
						columns: 1,
						rowHeight: 55,
					},
				})
				document.getElementById('containerTool').appendChild(stencil.container)
				for (var gindex = 0; gindex < resp.data.length; gindex++) {
					var group = resp.data[gindex]
					var nodeObjs = []
					for (var nindex = 0; nindex < group.nodes.length; nindex++) {
						var node = group.nodes[nindex]
						var items = []
						for (var pindex = 0; pindex < node.ports.length; pindex++) {
							let post = node.ports[pindex]
							items.push({group: post})
						}
						const nodeObj = that.graph.addNode({
							id: node.id,
							shape: node.shape,
							data: node,
							ports: {
								items: items
							},
							nodeMovable: true
						})
						nodeObjs.push(nodeObj)
					}
					stencil.load(nodeObjs, group.name)
				}
			})
		},
		initTool() {
			graphRegister();
			that.graph.on('cell:mouseenter', ({cell}) => {
				if(that.jobState == 'READY'){
					cell.addTools([
						{
							name: 'button-remove',
							args: {
								x: 0,
								y: 0,
								offset: {x: 10, y: 10},
							},
						}
					])
				}
				if (cell.isNode()) {
					cell.addTools([
						{
							name: 'boundary',
							args: {
        						padding: 5,
								attrs: {
									//fill: '#7c68fc',
									//stroke: '#333',
									strokeWidth: 0,
									fillOpacity: 0,
								},
							},
						}
					])
				}
			})
			that.graph.on('cell:mouseleave', ({cell}) => {
				cell.removeTools()
			})
		},
		init(data) {
			const cells = []
			if(!data.nodes){
				data['nodes'] = []
				data['edges'] = []
			}
			data.nodes.forEach((item) => {
				item.ports.groups = defaultPorts.groups
				item["position"] = {
					"x": item.x,
					"y": item.y
				}
				cells.push(that.graph.createNode(item))
			})
			data.edges.forEach((item) => {
				item["attrs"] = {
					"line": {
						"strokeDasharray": "5 5"
					},
					"targetMarker": {
						"name": "block",
						"width": 12,
						"height": 8
					}
				}
				cells.push(that.graph.createEdge(item))
			})
			that.graph.resetCells(cells)
			that.loadJobState()
		},
		loadTaskLog(nodeId){
			getRequst('/jobTask/taskLog?projectId=' + that.projectId + "&flowId=" + that.flowId + "&nodeId=" + nodeId).then(function (resp) {
				that.jobLogDrawer = true
				that.jobLogDrawerText = resp.data;
			})
		},
		loadJobState(){
			getRequst('/jobTask/state?projectId=' + that.projectId + "&flowId=" + that.flowId).then(function (resp) {
				if(resp.status == 0){
					that.jobState = resp.data
					that.loadTaskLogs()
					that.loadResultDatas()
					// 如果任务处于运行状态，那么一直获取
					if(resp.data == 'RUNNING'){
						setTimeout(function(){
							that.loadJobState();
						},2500)
					}
				}else{
					that.jobState = "READY"
				}
			})
		},
		loadTaskStatus(){
			getRequst('/jobTask/taskStatus?projectId=' + that.projectId + "&flowId=" + that.flowId).then(function (resp) {
				const allCells = that.graph.getCells();
				allCells.forEach((cell) => {
					resp.data.forEach((statusVo) => {
						if(cell.id == statusVo.graphNodeId){
							cell.prop('data/status', statusVo.status)
						}
						
					})
				})
			})
		},
		initEvent() {
			that.graph.on('node:click', ({e, x, y, node, view}) => {
				that.loadNodeAttr(node.id, node.getData().id)
			})
			/**that.graph.on('edge:click', ({e, x, y, edge, view}) => {
				console.log(edge)
				console.log(view)
			})**/
		},
		loadGraph() {
			if (!that.flowId) {
				that.$message({message: '请先创建训练流', type: "info"});
				return false;
			} else {
				getRequst('/graph/loadGraph?flowId=' + that.flowId).then(function (resp) {
					// 加载节点
					let data = []
					if (resp.status == 0 && resp.data) {
						data = JSON.parse(resp.data)
					}
					that.init(data)
					// 将画布内容中心与视口中心对齐
					that.graph.centerContent()
				})
			}
		},
		saveGraph() {
			let json = that.graph.toJSON()
			let cells = {}
			let nodes = []
			let edges = []
			for(index in json.cells){
				let cell = json.cells[index]
				if(cell.shape == "custom-html"){
					nodes.push({
						//"position": cell.position,
						"x": cell.position.x,
						"y": cell.position.y,
						"shape": cell.shape,
						"ports": {
							"items": cell.ports.items,
						},
						"id": cell.id,
						"data": cell.data,
						"zIndex": cell.zIndex
					})
				}else{
					edges.push({
						"shape": cell.shape,
						/**打开注释就有虚线**/
						/**"attrs": {
							"line": {
								"strokeDasharray": "5 5"
							},
							"targetMarker": {
								"name": "block",
								"width": 12,
								"height": 8
							}
						},**/
						"id": cell.id,
						"zIndex": cell.zIndex,
						"source": cell.source,
						"target": cell.target,
					})
				}
			}
			cells = {
				nodes,
				edges
			}
			console.log('保存 end')
			let pp = {
				"flowId": that.flowId,
				"grapJson": JSON.stringify(cells),
			}
			postRequst('/graph/saveGraph', pp, true).then(function (resp) {
				if (resp.status == 0) {
					that.$message({message: resp.msg, type: "success"});
				} else {
					that.$message({message: resp.msg, type: "error"});
				}
			})
		},
		loadFlows() {
			let that = this
			that.flowId = null
			getRequst('/project/loadFlows?projectId=' + that.projectId).then(function (resp) {
				that.flowData = resp.data
				if (resp.data.length > 0) {
					that.$refs.flowTableRef.setCurrentRow(resp.data[0])
					that.flowId = resp.data[0].flowId
				}
			})
		},
		loadNotAuthData(nodeId) {
			let that = this
			getRequst('/data/notAuthData?projectId=' + that.projectId + '&nodeId=' + nodeId).then(function (resp) {
				that.notAuthDatas = resp.data
			})
		},
		loadInvite() {
			let that = this
			getRequst('/project/invites?projectId=' + that.projectId).then(function (resp) {
				that.inviteData = resp.data
			})
		},
		openInvite(inviteId, nodeId){
			that.selectInviteId = inviteId
			that.selectNodeId = nodeId
			that.loadNotAuthData(nodeId)
		},
		closeInvite(){
			that.selectInviteId = null
		},
		saveInvite(){
			if(!that.selectDataId){
				that.$message({message: "请选择授权数据", type: "warning"});
				return false;
			}
			that.saveReadData()
		},
		saveReadData() {
			let pp = {
				"projectId": that.projectId,
				"flowId": that.flowId,
				"nodeId": that.selectNodeId,
				"dataId": that.selectDataId,
			}
			postRequst('/project/saveReadData', pp, true).then(function (resp) {
				if (resp.status == 0) {
					that.selectInviteId = null
					that.selectNodeId = null
					that.selectDataId = null
					that.loadInvite()
					that.$message({message: resp.msg, type: "success"});
				} else {
					that.$message({message: resp.msg, type: "error"});
				}
			})
		},
		saveFlow() {
			if (!that.flowTitle) {
				that.$message({message: "请输入", type: "warning"});
				return false;
			}
			let pp = {
				projectId: that.projectId,
				flowTitle: that.flowTitle
			}
			postRequst('/project/saveFlow', pp, true).then(function (resp) {
				if (resp.status == 0) {
					that.loadFlows()
					that.flowFormVisible = false
					that.flowTitle = ''
					that.$message({message: resp.msg, type: "success"});
				} else {
					that.$message({message: resp.msg, type: "error"});
				}
			})
		},
		delFlow(flowId) {
			that.$messageBox.confirm('该操作将移除训练流所有相关数据跟进程，是否继续?')
				.then(() => {
					getRequst('/project/removeFlow?flowId=' + flowId).then(function (resp) {
						if (resp.status == 0) {
							that.loadFlows()
							that.$message({message: resp.msg, type: "success"});
						} else {
							that.$message({message: resp.msg, type: "error"});
						}
					})
				})
				.catch(() => {
					// catch error
				})
		},
		handleFlowChange(val) {
			that.flowId = val.flowId
			that.loadGraph()
			that.canRedo = false
			that.canUndo = false
			that.loadJobState()
		},
		loadNodeAttr(graphId, nodeCode) {
			let that = this
			let pp = {
				projectId: that.projectId,
				flowId: that.flowId,
				graphId: graphId,
				nodeCode: nodeCode
			}
			that.nodeAttrForm = {}
			postRequst('/graph/loadNodeAttr?t=' + new Date().getTime(), pp, true).then(function (resp) {
				if(resp.status == 1){
					that.$message({message: resp.msg, type: "error"});
					return false;
				}
				that.nodeAttrForm = resp.data
				that.nodeAttrForm.showDef = false
				let showSwitch = false
				if(resp.data.attrs && resp.data.attrs.length > 0){
					for(attrIndex in resp.data.attrs){
						if(resp.data.attrs[attrIndex].required == false){
							showSwitch = true
						}
					}
				}
				that.nodeAttrForm.showSwitch = showSwitch
				that.activeCollapse= 'needAttr'
			})
		},
		saveNodeAttr() {
			let that = this
			this.$refs['nodeAttrForm'].validate((valid) => {
				if(valid){
					that.nodeAttrForm.projectId = that.projectId
					that.nodeAttrForm.flowId = that.flowId
					console.log(that.nodeAttrForm)
					postRequst('/graph/saveNodeAttr', that.nodeAttrForm).then(function (resp) {
						if (resp.status == 0) {
							that.$message({message: resp.msg, type: "success"});
						} else {
							that.$message({message: resp.msg, type: "error"});
						}
					})
				}else{
					that.activeCollapse= 'needAttr'
				}
			})
		},
		loadTaskLogs() {
			let that = this
			if (that.flowId) {
				let pp = {
					projectId: that.projectId,
					flowId: that.flowId
				}
				getRequst('/jobTask/loadTaskLogs', pp).then(function (resp) {
					that.taskLogs = resp.data
				})
			}
		},
		loadResultDatas() {
			let that = this
			if (that.flowId) {
				let pp = {
					projectId: that.projectId,
					flowId: that.flowId
				}
				getRequst('/jobResult/loadResultDatas', pp).then(function (resp) {
					that.resultDatas = resp.data
				})
			}
		},
		startJob(jobType){
			that.$messageBox.confirm('是否确定流程所需数据配置完成?')
			.then(() => {
				if (!that.flowId) {
					that.$message({message: "请选择执行的训练流", type: "warning"});
					return false;
				}
				let pp = {
					projectId: that.projectId,
					flowId: that.flowId,
					graphNodeId: '',
					jobType: jobType
				}
				if(jobType == 1){
					pp.graphNodeId = that.graphSelectNode.id
				}
				postRequst('/jobTask/startJob', pp, true).then(function (resp) {
					if (resp.status == 0) {
						that.loadJobState();
						that.$message({message: resp.msg, type: "success"});
					} else {
						that.$message({message: resp.msg, type: "error"});
					}
				})
			})
			.catch(() => {
				// catch error
			})
		},
		stopJob(){
			that.$messageBox.confirm('是否确定停止运行任务?')
			.then(() => {
				if (!that.flowId) {
					that.$message({message: "请选择执行的训练流", type: "warning"});
					return false;
				}
				let pp = {
					projectId: that.projectId,
					flowId: that.flowId,
				}
				postRequst('/jobTask/stopJob', pp, true).then(function (resp) {
					if (resp.status == 0) {
						that.$message({message: resp.msg, type: "success"});
					} else {
						that.$message({message: resp.msg, type: "error"});
					}
				})
			})
			.catch(() => {
				// catch error
			})
		},
		noedAttrHandle(graphId, nodeCode, attrCode, index){
			let that = this
			let pp = {
				projectId: that.projectId,
				flowId: that.flowId,
				graphId: graphId,
				nodeCode: nodeCode,
				attrCode: attrCode,
				attrIndex: index
			}
			postRequst('/graph/renderAttrValue', pp, true).then(function (resp) {
				console.log(resp)
				if (resp.status == 0) {
					that.attrConfigDrawer = true
					that.attrForm = Object.assign({}, resp.data, pp);
				} else {
					that.$message({message: resp.msg, type: "error"});
				}
			})
		},
		cancelAttrConfigClick(){
			this.attrConfigDrawer = false
		},
		confirmAttrConfigClick(){
			let that = this
			if(!this.attrForm.value || this.attrForm.value.length == 0){
				that.$message({message: '请选择', type: "error"});
				return false;
			}
			let value = that.attrForm.value.join(',')
			that.nodeAttrForm.attrs[that.attrForm.attrIndex].prop = value
			this.attrConfigDrawer = false
		},
		showResultData(domainDataId){
			let that = this
			getRequst('/data/showResultData?projectId=' + that.projectId + "&flowId=" + that.flowId 
				+ "&domainDataId=" + domainDataId).then(function (resp) {
				that.$message({message: '请打开控制台查看数据', type: "error"});
				console.log(resp)
			})
		}
	}
	function _created() {
		this.projectId = urlParam('id')
		if(!this.projectId){
			alert('请重新选择项目')
			return ;
		}
		getRequst('/project/info?projectId=' + this.projectId).then(function (resp) {
			that.project = resp.data
			that.loadFlows()
			that.loadInvite()
			that.initGraph()
		})
		window.addEventListener('resize', function(){
			that.$nextTick(() => {
				var elelMianRef = that.$refs.elelMian.$el;
				if(elelMianRef){
					that.elelMianHeight = elelMianRef.clientHeight;
					that.graph.resize('100%', that.elelMianHeight * 1 - 130);
				}
			})
		});
	}
	const _watch = {
		jobState(nval,oval) {
			if(nval == 'RUNNING'){
				// 如果项目处于运行中，那么又定时器触发查询
				that.taskStatueInterval = setInterval(() => {
				    that.loadTaskStatus();
				}, 3000);
			}else if(nval && nval != 'READY'){
				if(that.taskStatueInterval != null){
					// 关闭任务定时器
					clearInterval(that.taskStatueInterval)
				}
				that.loadTaskStatus();
			}
		}
	}
	const _components = {
		"node-attr": '/base/js/component/nodeAttr.vue',
		"node-log": '/base/js/component/nodeLog.vue',
		"node-ind": '/base/js/component/nodeInds.vue'
	}
</script>

</html>